﻿
namespace SwtorCalculator.Talent {
    using System;
    using System.Collections.Generic;
    using System.Reflection;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using Talents;

    /// <summary>
    /// Interaction logic for TalentPanel.xaml
    /// </summary>
    public partial class TalentPanel : UserControl {
        private const string PREFIX = @"pack://application:,,,/SwtorCalculator;component/Images/TalentCalc/";
        internal EventHandler TalentsChanged;
        private ImageBrush[] panelBGs = {
                                        new ImageBrush( new BitmapImage( new Uri( PREFIX + "TreeOneBG.png", UriKind.Absolute ) ) ),
                                        new ImageBrush( new BitmapImage( new Uri( PREFIX + "TreeTwoBG.png", UriKind.Absolute ) ) ),
                                        new ImageBrush( new BitmapImage( new Uri( PREFIX + "TreeThreeBG.png", UriKind.Absolute ) ) ) };
        private Dictionary<int, int> belowRow;
        private Dictionary<int, TalentDataAttribute> talentAttributes;
        private Dictionary<int, Image> prereqArrows;

        /// <summary>
        /// TalentPanel no-arg constructor
        /// </summary>
        public TalentPanel() {
            InitializeComponent();
            talentAttributes = new Dictionary<int, TalentDataAttribute>();
            prereqArrows = new Dictionary<int, Image>();
            belowRow = new Dictionary<int, int>();
        }

        internal int Tree { get; set; }
        internal string TreeName { get; private set; }

        private TalentBase charTalents;
        internal TalentBase CharacterTalents {
            get { return charTalents; }
            set {
                if( value != null ) {
                    charTalents = value;
                    for( int r = 1; r <= 7; r++ ) {
                        for( int c = 1; c <= 4; c++ ) {
                            this[r, c].TalentData = null;
                        }
                    }
                    talentAttributes.Clear();
                    belowRow.Clear();
                    if( prereqArrows != null ) {
                        foreach( KeyValuePair<int, Image> kvp in prereqArrows ) {
                            GridPanel.Children.Remove( kvp.Value );
                        }
                    }

                    prereqArrows.Clear();
                    TreeName = CharacterTalents.TreeNames[Tree];
                    foreach( PropertyInfo pi in CharacterTalents.GetType().GetProperties() ) {
                        TalentDataAttribute[] talentDatas = pi.GetCustomAttributes( typeof( TalentDataAttribute ), true ) as TalentDataAttribute[];
                        if( talentDatas.Length > 0 ) {
                            TalentDataAttribute talentData = talentDatas[0];
                            if( talentData.Tree != Tree )
                                continue;

                            this[talentData.Row, talentData.Column].TalentData = talentData;
                            talentAttributes[talentData.Index] = talentData;
                        }
                    }

                    for( int r = 1; r <= 7; r++ ) {
                        for( int c = 1; c <= 4; c++ ) {
                            this[r, c].Update();
                        }
                    }

                    UpdatePrereqs();

                    if( GridPanel.Background != panelBGs[Tree] )
                        GridPanel.Background = panelBGs[Tree];
                }
            }
        }

        internal void RankChanged() {
            belowRow.Clear();
            for( int r = 1; r <= 7; r++ ) {
                for( int c = 1; c <= 4; c++ ) {
                    this[r, c].Update();
                }
            }

            UpdatePrereqs();
            if( TalentsChanged != null )
                TalentsChanged.Invoke( this, EventArgs.Empty );
        }

        internal int PointsBelowRow( int row ) {
            if( belowRow.ContainsKey( row ) )
                return belowRow[row];
            else {
                int pts = 0;
                for( int r = row; r > 0; r-- ) {
                    for( int c = 1; c <= 4; c++ ) {
                        pts += this[r, c].Current;
                    }
                }

                belowRow[row] = pts;
                return pts;
            }
        }

        internal int Points() {
            return PointsBelowRow( 7 );
        }

        internal TalentDataAttribute GetAttribute( int index ) {
            if( talentAttributes.ContainsKey( index ) )
                return talentAttributes[index];
            else
                return null;
        }

        internal void UpdatePrereqs() {
            foreach( KeyValuePair<int, TalentDataAttribute> kvp in talentAttributes ) {
                if( kvp.Value.Prerquisite >= 0 ) {
                    TalentDataAttribute prereq = GetAttribute( kvp.Value.Prerquisite );
                    int row = kvp.Value.Row - prereq.Row;
                    int col = kvp.Value.Column - prereq.Column;

                    string suffix;
                    if( kvp.Value.MaxPoints == CharacterTalents.PointsSpent[kvp.Value.Index] )
                        suffix = "Gold.png";
                    else if( PointsBelowRow( kvp.Value.Row ) >= ( kvp.Value.Row - 1 ) * 5 && CharacterTalents.PointsSpent[prereq.Index] == prereq.MaxPoints )
                        suffix = "Blue.png";
                    else
                        suffix = "Gray.png";

                    Image image;
                    if( prereqArrows.ContainsKey( kvp.Value.Index ) ) {
                        image = prereqArrows[kvp.Value.Index];
                    }

                    else {
                        image = new Image();
                        Grid.SetColumn( image, kvp.Value.Column );
                        Grid.SetRow( image, ReverseRow( kvp.Value.Row ) );
                        image.Stretch = Stretch.Fill;
                        image.SetBinding( Image.WidthProperty, new System.Windows.Data.Binding() { Path = new PropertyPath( "Source.PixelWidth" ), RelativeSource = new System.Windows.Data.RelativeSource( System.Windows.Data.RelativeSourceMode.Self ) } );
                        image.SetBinding( Image.HeightProperty, new System.Windows.Data.Binding() { Path = new PropertyPath( "Source.PixelHeight" ), RelativeSource = new System.Windows.Data.RelativeSource( System.Windows.Data.RelativeSourceMode.Self ) } );
                        image.HorizontalAlignment = HorizontalAlignment.Left;
                        image.VerticalAlignment = VerticalAlignment.Top;
                        //image.SetValue( Grid.ZIndexProperty, 3 ); //FOR TESTING
                        GridPanel.Children.Add( image );
                        
                        prereqArrows[kvp.Value.Index] = image;
                    }

                    if( row == 0 ) {
                        if( col == -1 ) {
                            image.Source = new BitmapImage( new Uri( PREFIX + "LeftConnect" + suffix, UriKind.Absolute ) );
                            image.Margin = new Thickness( 55, 28, 0, 0 );
                            Grid.SetColumnSpan( image, 2 );
                        }
                        else if( col == 1 ) {
                            image.Source = new BitmapImage( new Uri( PREFIX + "RightConnect" + suffix, UriKind.Absolute ) );
                            image.Margin = new Thickness( -1, 28, 0, 0 );
                            Grid.SetColumnSpan( image, 2 );
                        }
                    }

                    else if( row == 1 ) {
                        image.Source = new BitmapImage( new Uri( PREFIX + "BottomConnect" + suffix, UriKind.Absolute ) );
                        image.Margin = new Thickness( 30, 55, 0, 0 );
                        Grid.SetRowSpan( image, 2 );
                    }

                    else if( row == 2 ) {
                        image.Source = new BitmapImage( new Uri( PREFIX + "MidConnect" + suffix, UriKind.Absolute ) );
                        image.Margin = new Thickness( 30, 62, 0, 0 );
                        Grid.SetRowSpan( image, 3 );
                    }
                }
            }
        }

        private TalentButton this[int row, int col] {
            get {
                if( row == 1 ) {
                    if( col == 1 ) return Talent_1_1;
                    if( col == 2 ) return Talent_1_2;
                    if( col == 3 ) return Talent_1_3;
                    if( col == 4 ) return Talent_1_4;
                }
                else if( row == 2 ) {
                    if( col == 1 ) return Talent_2_1;
                    if( col == 2 ) return Talent_2_2;
                    if( col == 3 ) return Talent_2_3;
                    if( col == 4 ) return Talent_2_4;
                }
                else if( row == 3 ) {
                    if( col == 1 ) return Talent_3_1;
                    if( col == 2 ) return Talent_3_2;
                    if( col == 3 ) return Talent_3_3;
                    if( col == 4 ) return Talent_3_4;
                }
                else if( row == 4 ) {
                    if( col == 1 ) return Talent_4_1;
                    if( col == 2 ) return Talent_4_2;
                    if( col == 3 ) return Talent_4_3;
                    if( col == 4 ) return Talent_4_4;
                }
                else if( row == 5 ) {
                    if( col == 1 ) return Talent_5_1;
                    if( col == 2 ) return Talent_5_2;
                    if( col == 3 ) return Talent_5_3;
                    if( col == 4 ) return Talent_5_4;
                }
                else if( row == 6 ) {
                    if( col == 1 ) return Talent_6_1;
                    if( col == 2 ) return Talent_6_2;
                    if( col == 3 ) return Talent_6_3;
                    if( col == 4 ) return Talent_6_4;
                }
                else if( row == 7 ) {
                    if( col == 1 ) return Talent_7_1;
                    if( col == 2 ) return Talent_7_2;
                    if( col == 3 ) return Talent_7_3;
                    if( col == 4 ) return Talent_7_4;
                }

                return null;
            }
        }

        private int ReverseRow( int rc ) {
            switch( rc ) {
                case 1:
                    return 7;
                case 2:
                    return 6;
                case 3:
                    return 5;
                case 5:
                    return 3;
                case 6:
                    return 2;
                case 7:
                    return 1;
            }

            return 4;
        }
    }
}
